﻿// <author>Netmon Cipher Dev Team</author>
// <date>2009-07-16</date>
// <version>1.0</version>
// <summary>
// This class implements the IDecryptCapture
// interface of Common Framework.
// </summary>

namespace DecryptionExpertFramework
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Xml;
    using SSLDecryptionExpert;    

    /// <summary>
    /// Operation Status Enum
    /// </summary>
    public enum Status
    {
        /// <summary>
        /// Thread in Working State
        /// </summary>
        Working,

        /// <summary>
        /// The Decryption thread is complete
        /// </summary>
        Done
    }

    /// <summary>
    /// This class implements the IDecryptCapture
    /// interface of Common Framework.
    /// </summary>
    public class DecryptNetmonCapture : IDecryptCapture
    {
        #region Member Variables

        /// <summary>
        /// Set to TRUE if Server Certificate password 
        /// is mismatched
        /// </summary>
        private bool passwordMismatch;

        /// <summary>
        /// Set to TRUE if Server Certificate 
        /// is reported to be invalid by Expert.
        /// </summary>
        private bool incorrectCertificate;

        /// <summary>
        /// Holds Status Message from SSL Library.
        /// </summary>
        private string statusMessage = string.Empty;

        /// <summary>
        /// Stores the status of main thread.
        /// </summary>
        private Status status = Status.Working;

        /// <summary>
        /// Status String.for error conditions
        /// </summary>
        private string decryptionResult = string.Empty;        

        /// <summary>
        /// Stores decryption result
        /// </summary>
        private bool result = false;

        /// <summary>
        /// Config File Path
        /// </summary>
        private string configFile = string.Empty;

        /// <summary>
        /// Set to True, if SSL protocol is selected
        /// </summary>
        private bool isSSLSelcted = false;       

        /// <summary>
        /// Delegate to log progress information
        /// </summary>
        /// <param name="statusMessage">Status Message</param>
        public delegate void LogEventHandler(string statusMessage);

        /// <summary>
        /// Event which captures the status message
        /// </summary>
        public event LogEventHandler Log;

        /// <summary>
        /// Gets Error Message
        /// </summary>
        public string ErrorText
        {
            get { return this.decryptionResult; }
        }

        /// <summary>
        /// Gets a value indicating whether successful decryption occurred
        /// </summary>
        public bool DecryptionSuccessful
        {
            get { return this.result; }
        }

        /// <summary>
        /// Gets a value indicating whether the user typed an incorrect password
        /// </summary>
        public bool PasswordMismatch
        {
            get { return this.passwordMismatch; }
        }

        /// <summary>
        /// Gets a value indicating whether an incorrect certificate was provided
        /// </summary>
        public bool IncorrectCertificate
        {
            get { return this.incorrectCertificate; }
        }

        #endregion

        /// <summary>
        /// To decrypt the Encrypted Capture File
        /// </summary>
        /// <param name="configFile">XML Configuration File</param>
        /// <param name="decryptionResult">Decryption Status message</param>
        /// <returns>Returns TRUE if Decryption is Successful.</returns>
        public bool DecryptCapture(
                        string configFile,
                        out string decryptionResult)
        {
            decryptionResult = string.Empty;
            this.passwordMismatch = false;
            this.incorrectCertificate = false;
            this.configFile = configFile;            

            this.GetSelectedProtocols();

            if (this.isSSLSelcted)
            {
                SSLDecryption objDecryption = new SSLDecryption();

                //// Subscribe the function
                objDecryption.Log += new SSLDecryption.LogEventHandler(this.UpdateStatus);

                ParameterizedThreadStart updateInfo =
                            new ParameterizedThreadStart(this.SslDecrypt);
                Thread thread = new Thread(updateInfo);
                thread.Start(objDecryption);

                while (this.status == Status.Working)
                {
                    objDecryption.UpdateStatusInfo();
                }
            }            

            decryptionResult = this.decryptionResult;
            this.passwordMismatch = Variables.passwordMismatch;
            this.incorrectCertificate = Variables.incorrectCertificate;
            return this.result;
        }

        /// <summary>
        /// Updates the status message
        /// </summary>
        /// <param name="newMessage">New Message to update.</param>
        public void UpdateStatus(string newMessage)
        {
            this.statusMessage = newMessage;
        }

        /// <summary>
        /// Updates the status information.
        /// </summary>
        public void UpdateProgressBar()
        {
            if (this.Log != null)
            {
                this.Log(this.statusMessage);
            }
        }

        /// <summary>
        /// This method sets the values of selected protocols
        /// </summary>
        public void GetSelectedProtocols()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(this.configFile);
            XmlNodeList nodeList = doc.SelectNodes("/config/Protocols/Protocol");
            foreach (XmlNode node in nodeList)
            {
                if (node.Attributes[0].Value.Equals("SSL", StringComparison.OrdinalIgnoreCase) &&
                    node.Attributes[1].Value.Equals("TRUE", StringComparison.OrdinalIgnoreCase))
                {
                    this.isSSLSelcted = true;
                }
            }
        }  

        /// <summary>
        /// Calls SSL Decryption Library
        /// </summary>
        /// <param name="obj">
        /// Object of SSL Decryption Library
        /// </param>
        private void SslDecrypt(object obj)
        {
            Dictionary<string, string> property =
                DefUtils.GetConfigProperties(this.configFile);

            SSLDecryption decryptionObject = (SSLDecryption)obj;
            bool res = decryptionObject.SslDecryptCapture(
                                            property,
                                            out this.decryptionResult);

            //// Assigning to global result variable.
            this.result = res;

            // Moving to UI...
            /*if (res)
            {
                try
                {
                    System.Diagnostics.Process openCap = new System.Diagnostics.Process();
                    openCap.StartInfo.FileName = ProcessName;
                    openCap.StartInfo.Arguments = property["DecryptedCaptureFile"];
                    openCap.Start();
                    this.decryptionResult = property["EncryptedCaptureFile"] +
                                        " is Sucessfully Decrypted";
                }
                catch
                {
                    this.decryptionResult = "Error in opening Decrypted Capture File: "
                                       + property["DecryptedCaptureFile"];
                    res = false;
                }
            }*/
          
            //// Deletes the file if Decryption has failed.
            //if (!res)
            //{
            //    if (System.IO.File.Exists(property["DecryptedCaptureFile"]))
            //    {
            //        System.IO.File.Delete(property["DecryptedCaptureFile"]);
            //    }
            //}

            //// Setting status to DONE
            this.status = Status.Done;
        }
    }
}
